/*
 * Copyright 2011 Kim Lindhardt Madsen
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package dk.lindhardt.gwt.geie.client;

import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.user.client.Element;

import java.util.Date;

/**
 * User: AnAmuser
 * Date: 07-06-11
 * <p/>
 * Client utility functions
 */
public class Util {

   /**
    * Gets timezone offset in minutes from UTC for a given date. It also takes care of daylight time correction.
    * @param date the date
    * @return offset in minutes
    */
   public static int getClientTimeZoneOffset(Date date) {
      String Z = DateTimeFormat.getFormat("Z").format(date).replace("+", "");
      boolean negative = Z.contains("-");
      int hours = Integer.parseInt(Z.substring(0, negative ? 3 : 2));
      int minutes = Integer.parseInt(Z.substring(negative ? 3 : 2));
      return hours * 60 + minutes;
   }

   /**
    * @return IE version of the client (Defaults to -1 if not IE)
    */
   static native float getIEVersion() /*-{
      var ua = navigator.userAgent;
      var MSIEOffset = ua.indexOf(
            "MSIE ");

      if (MSIEOffset == -1) {
         return 0;
      } else {
         return parseFloat(
               ua.substring(
                     MSIEOffset + 5,
                     ua.indexOf(
                           ";", MSIEOffset)));
      }
   }-*/;

   /**
    * Gets the value of some css property. Fx <code>"font-size"</code>.
    * This method returns used values. Read on internet to see difference used and computed values.
    * @param element the element with style
    * @param styleAttribute the style property
    * @return the css property
    */
   static native String getUsedStyle(float IEVersion, Element element, String styleAttribute) /*-{
      if (IEVersion >= 6.0) {
         return element.currentStyle[styleAttribute] + '';
      } else {
         return window.getComputedStyle(
               element, null).getPropertyValue(
               styleAttribute);
      }
   }-*/;

   /**
    * Gets px size from fx "1.8em" or "small" calculated on a 16ppem base and with css2 suggested scale factor of 1.2
    * @param size the string
    * @return size as int
    */
   static int getPxSize(String size) {
      if (size != null && size.length() > 0) {
         if (size.endsWith("px")) {
            String px = size.substring(0, size.length() - 2);
            return Integer.parseInt(px);
         } else if (size.endsWith("em")) {
            String em = size.substring(0, size.length() - 2);
            float px = Float.parseFloat(em) * 16.0f;
            return Math.round(px);
         } else if (size.endsWith("pt")) {
            String pt = size.substring(0, size.length() - 2);
            float em = (Float.parseFloat(pt) - 6.0f) * 0.05f + 0.50f;
            float px = em * 16.0f;
            return Math.round(px);
         } else if (size.equals("x-small")) {
            return 9;
         } else if (size.equals("x-small")) {
            return 11;
         } else if (size.equals("small")) {
            return 13;
         } else if (size.equals("medium")) {
            return 16;
         } else if (size.equals("large")) {
            return 19;
         } else if (size.equals("x-large")) {
            return 23;
         } else if (size.equals("xx-large")) {
            return 28;
         }
      }
      return 0;
   }

   /**
    * Sums over a number of items in an array from the given start index. If the index is larger than the array
    * length the given default value will be used.
    * @param array the array to sum over
    * @param startIndex the index to start from
    * @param items number of items to sum
    * @param defaultValue the default value used when <code>index > array.length</code>
    * @return the result
    */
   static double sum(Integer[] array, double startIndex, double items, double defaultValue) {
      double result = 0;

      if (items > 0) {
         int floorStart = (int) Math.floor(startIndex);
         double leftEnd = startIndex - floorStart;
         if (floorStart < array.length) {
            result += array[floorStart] * leftEnd;
         } else {
            result += defaultValue * leftEnd;
         }

         double itemsLeft = items - leftEnd;
         int i = 0;
         for (; i < itemsLeft; i++) {
            if (floorStart + i < array.length) {
               result += array[floorStart + i];
            } else {
               result += defaultValue;
            }
         }

         double rightEnd = itemsLeft - i;
         if (rightEnd > 0) {
            if (floorStart + i < array.length) {
               result += array[floorStart + i] * rightEnd;
            } else {
               result += defaultValue * rightEnd;
            }
         } else {
            if (floorStart + i - 1 < array.length) {
               result += array[floorStart + i - 1] * rightEnd;
            } else {
               result += defaultValue * rightEnd;
            }
         }
      }

      return result;
   }
}
